<?php

namespace App\Http\Controllers\App\V1;

use App\Models\MainDB\UserAuthBlacklist;
use Exception;
use App\Enums\ActionEnum;
use App\Enums\SmsTypeEnum;
use App\Services\Tools\CurlService;
use Carbon\Carbon;
use App\Response\Response;
use App\Services\Tools\SmsService;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Cache;
use App\Http\Controllers\BaseController;
use Illuminate\Http\Request;        //引用http请求类
use App\Exceptions\BasicException;  //引入框架异常处理类

use Alipay\EasySDK\Kernel\Factory;
use Alipay\EasySDK\Kernel\Util\ResponseChecker;
use Alipay\EasySDK\Kernel\Config;
use Alipay\EasySDK\Member\Identification\Models\IdentityParam;
use Alipay\EasySDK\Member\Identification\Models\MerchantConfig;

class AlipayAuthController extends BaseController {
    public function __construct() {
        $options = new Config();
        $options->protocol = 'https';
        $options->gatewayHost = 'openapi.alipay.com';
        $options->signType = 'RSA2';
        $options->appId = env('ALIPAY_APP_ID');
        // 为避免私钥随源码泄露，推荐从文件中读取私钥字符串而不是写入源码中
        $options->merchantPrivateKey = env('ALIPAY_PRIVATE_KEY');
        //注：如果采用非证书模式，则无需赋值上面的三个证书路径，改为赋值如下的支付宝公钥字符串即可
        $options->alipayPublicKey = env('ALIPAY_PUBLIC_KEY');
        Factory::setOptions($options);
    }

    public function initialize(Request $request) {
        try {
            $certName = $request->input('certName');
            $certNo = $request->input('certNo');
            $code = $request->input('code');
            if (!$certName) {
                throw new BasicException(20002);
            }
            if (!checkCertNo($certNo)) {
                throw new BasicException(20003);
            }

            if(!isAdult($certNo))
            {
                throw new BasicException(120003);
            }

            // 验证身份证号是否被拉黑
            $isBan = UserAuthBlacklist::query()->where("id_number", $certNo)->exists();
            if($isBan){
                throw new BasicException(-1, "已加入实名黑名单");
            }

            $user_id = UID;
            $mobile = app('repo_user')->getUserMobile($user_id);
            if (!$mobile) {
                throw new BasicException(20009);
            }
            if (!SmsService::verify($mobile, $code, SmsTypeEnum::AUTH_QUICK)) {
                throw new BasicException(20010);
            }
            $detail = app('repo_user_auth')->getUserAuth($user_id);
            if ($detail) {
                if ($detail->app_status == 0) {
                    throw new BasicException(20007);
                } elseif ($detail->app_status == 1) {
                    throw new BasicException(20008);
                }
            }

            //每天限制提交5次
            $key = 'auth:alipay:' . $user_id;
            $times = Cache::get($key);
            if ($times >= 5) {
                throw new BasicException(20011);
            }

            $identityParam = new IdentityParam();
            $identityParam->identityType = "CERT_INFO";
            $identityParam->certType = "IDENTITY_CARD";
            $identityParam->certName = $certName;
            $identityParam->certNo = $certNo;

            $merchantConfig = new MerchantConfig();
            $order_no = createOrderSn();
            $merchantConfig->returnUrl = env('ALIPAY_CALLBACK_URL') . '?order_no=' . $order_no;
            $result = Factory::member()->identification()->init($order_no, 'SMART_FACE', $identityParam, $merchantConfig);
            $responseChecker = new ResponseChecker();
            if ($responseChecker->success($result)) {
                $certify_id = $result->certifyId;
                $result_url = Factory::member()->identification()->certify($certify_id);
                if ($responseChecker->success($result_url)) {
                    $certify_url = $result_url->body;
                } else {
                    throw new BasicException(20001);
                }
                $res = app('model_alipay_auth')->create([
                    'user_id'    => $user_id,
                    'order_no'   => $order_no,
                    'cert_name'  => $certName,
                    'cert_no'    => $certNo,
                    'add_time'   => time(),
                    'certify_id' => $certify_id,
                ]);
                if (!$res) {
                    throw new BasicException(9001);
                }

                Cache::put($key, $times + 1, Carbon::tomorrow());

                return Response::sendData(['url' => $certify_url, 'certify_id' => $certify_id]);
            } else {
                Log::info($result->msg . "，" . $result->subMsg);
                throw new BasicException(20001);
            }
        } catch (Exception $e) {
            throw new BasicException(0, $e->getMessage());
        }
    }

    public function callback(Request $request) {
        $order_no = $request->input('order_no');
        if (!$order_no) {
            throw new BasicException(20005);
        }
        $data = app('model_alipay_auth')->where('order_no', $order_no)->first();
        if (!$data) {
            throw new BasicException(20006);
        }
        if ($data->status == 1) {
            return Response::sendData($data->status);
        } elseif($data->status == 2) {
            throw new BasicException(0, '认证失败,请重试');
        }
        $certify_id = $data->certify_id;
        try {
            $result = Factory::member()->identification()->query($certify_id);
            $responseChecker = new ResponseChecker();
            if ($responseChecker->success($result)) {
                $status = $result->passed == 'T' ? 1 : 2;
                app('model_alipay_auth')->where('status', 0)->where('id', $data->id)->update([
                    'status'      => $status,
                    'update_time' => time(),
                ]);

                app('model_user_auth')->create([
                    'user_id'    => $data->user_id,
                    'full_name'  => $data->cert_name,
                    'id_number'  => $data->cert_no,
                    'app_status' => $status,
                    'created_time' => Carbon::now(),
                    'update_time' => Carbon::now(),
                    'type'       => 2
                ]);
                if ($status == 1) {
                }

                return Response::sendData($status);
            } else {
                Log::info($result->msg . "，" . $result->subMsg);
                throw new BasicException(20001);
            }
        } catch (Exception $e) {
            throw new BasicException(20001);
        }
    }
}
